package rhinestone.Model;

import java.util.HashMap;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.io.Serializable;

import rhinestone.TUI.MainMenuUI;
import rhinestone.Vlad_GUI.NewJFrame;

/**
 * Represents a sale.
 * When the user selects the Sale option in the UI, SaleController creates a new empty sale.
 * Then the user adds product here, checks the sale out and the sale is moved to the SaleContainer.
 *
 * @author Group 2
 * @version 2010.12.15
 */
public class Sale implements Serializable {
    // instance variables
    private HashMap<Product, Integer> products; // <Product, amount>
	private HashMap<Pack, Integer> packs;
	private Staff staff;
	private Customer customer;
    private GregorianCalendar date;
    private String staffId;
	private String status;


    public Sale(Staff staff) {
        products = new HashMap<Product, Integer>();
		packs = new HashMap<Pack, Integer>();
		this.staff = staff;
    }

	public void addProduct(Product product, int amount) {
		products.put(product, amount);
	}

	public void addPack(Pack pack, int amount) {
		packs.put(pack, amount);
	}

	public Product getProduct(String barcode) {
		Iterator<Product> it = products.keySet().iterator();
		while(it.hasNext()) {
			Product product = it.next();
			if(product.getBarcode().equals(barcode))
				return product;
		}
		return null;
	}

	public Pack getPack(String barcode) {
		Iterator<Pack> it = packs.keySet().iterator();
		while(it.hasNext()) {
			Pack pack = it.next();
			if(pack.getBarcode().equals(barcode))
				return pack;
		}
		return null;
	}

	public int getAmount(Product product) {
		return products.get(product);
	}

	public int getAmount(Pack pack) {
		return packs.get(pack);
	}

	public void removeProduct(Product product, int amount) {
		int amountInSale = products.get(product);
		if(amountInSale <= amount) {
			products.remove(product);
			System.out.println("Item removed.");
		}
		else if(amount > 0) {
			amountInSale -= amount;
			products.put(product, amountInSale);
			System.out.println(amount + " item(s) removed.");
		}
		else
			System.err.println("Item NOT removed");
	}

	public void removePack(Pack pack, int amount) {
		int amountInSale = packs.get(pack);
		if(amountInSale <= amount) {
			packs.remove(pack);
			System.out.println("Pack removed.");
		}
		else if(amount > 0) {
			amountInSale -= amount;
			packs.put(pack, amountInSale);
			System.out.println(amount + " pack(s) removed.");
		}
		else
			System.err.println("Pack NOT removed");
	}

	public void addCustomer(Customer customer) {
		this.customer = customer;
	}
	
	public Customer getCustomer() {
		return customer;
	}

	public Staff getStaff() {
		return staff;
	}

	public int getItemCount() {
		int totalItems = 0;

		Iterator<Product> it1 = products.keySet().iterator();
		while(it1.hasNext())
			totalItems += products.get(it1.next());

		Iterator<Pack> it2 = packs.keySet().iterator();
		while(it2.hasNext()) {
			Pack pack = it2.next();
			int amountInSale = packs.get(pack);
			totalItems += pack.getItemCount() * amountInSale;
		}

		return totalItems;
	}

	public double getTotalPrice() {
		double totalPrice = 0;
		Iterator<Product> it = products.keySet().iterator();
		while(it.hasNext()) {
			Product product = it.next();
			totalPrice += product.getPrice() * products.get(product);
		}
		Iterator<Pack> it2 = packs.keySet().iterator();
		while(it2.hasNext()) {
			Pack pack = it2.next();
			totalPrice += pack.getPrice() * packs.get(pack);
		}
		return totalPrice;
	}

	public Iterator<Product> getProducts() {
		return products.keySet().iterator();
	}

	public Iterator<Pack> getPacks() {
		return packs.keySet().iterator();
	}

	public double applyCustomerDiscount(double price) {
		if(customer != null) {
			double totalDiscount = customer.getCraftsmanDiscount() + customer.getGeneralDiscount();
			if(totalDiscount > 20)
				totalDiscount = 20;
			return (price - (price / 100 * totalDiscount));
		}
		return price;
	}

	public boolean hasCustomer() {
		return (customer != null);
	}

	public void updateItemContainers() {
		Iterator<Product> it = products.keySet().iterator();
		while(it.hasNext()) {
			Product product = it.next();
			int amount = products.get(product);
			updateProduct(product, amount);
		}

		Iterator<Pack> it2 = packs.keySet().iterator();
		while(it2.hasNext()) {
			Pack pack = it2.next();
			int amount = packs.get(pack);
			updatePack(pack, amount);
		}
	}

	private void updateProduct(Product product, int amount) {
		int localAvailableAmount;
		if(NewJFrame.LOGGED_IN.getWorkingPlace() == Staff.DIY) {
			localAvailableAmount = product.getAmountInDIY();
			if(localAvailableAmount >= amount)
				product.setAmountInDIY(localAvailableAmount - amount);
			else {
				amount -= localAvailableAmount;
				product.setAmountInDIY(0);
				product.setAmountInTimberyard(product.getAmountInTimberyard() - amount);
			}
		}
		else if(NewJFrame.LOGGED_IN.getWorkingPlace() == Staff.TIMBERYARD) {
			localAvailableAmount = product.getAmountInTimberyard();
			if(localAvailableAmount >= amount)
				product.setAmountInTimberyard(localAvailableAmount - amount);
			else {
				amount -= localAvailableAmount;
				product.setAmountInTimberyard(0);
				product.setAmountInDIY(product.getAmountInDIY() - amount);
			}
		}
	}

	private void updatePack(Pack pack, int amount) {
		Iterator<Product> it = pack.getProducts().keySet().iterator();
		while(it.hasNext()) {
			Product product = it.next();
			int amountInPack = pack.getAmountInPack(product);
			for(int i = 0; i < amount; i++)
				updateProduct(product, amountInPack);
		}
	}
}
